<?php
defined('BASEPATH') or exit('No direct script access allowed');

class SystemCheck extends MY_Controller
{

    public function __construct()
    {
        parent::__construct();
        $this->load->model('TopicUnit');
        $this->load->model('Debug');
    }

    public function index()
    {
        $this->errorInfoShow();
    }

    /* debug单例模式 */
    public function singleDebug($topicId)
    {
        $data = array();
        /* 请求接口 */
        $condition = array(
            '_id' => new MongoId($topicId)
        );
        $result = $this->TopicUnit->find($condition);
        $topic = $result[0];
        $topicName = $topic['topic_name'];
        $question = isset($_REQUEST['question']) ? $_REQUEST['question'] : $topicName; // 测试问题
        $source = $topic['source'];
        $url = sprintf(DEBUG_SINGLE, $topicId, urlencode($question), $source);
        $content = file_get_contents($url);
        if ($content === false) {
            $error = "Request Error --> $url 请求失败！";
            log_message('error', $error);
            return false;
        }
        $content = json_decode($content, true);
        $responseHead = $content['response_head'];
        if (1 == $responseHead['status']) {
            $error = "SingleDebug Error --> topicId : $topicId";
            log_message('error', $error);
            return false;
        }
        /* 解析数据 */
        $response = $content['response'];
        $topic = $response[$question]; // 测试话题
        $checkState = $topic['测试状态']; // 测试状态
        if ('ERROR' == $checkState) {
            $data = $this->singleDebugErrorType($topic);
        }
        $data['topicId'] = $topicId; // topic_id
        $data['topicName'] = $topicName; // 标准问题
        $data['question'] = $question; // 测试问题
        $data['checkState'] = $topic['测试状态']; // 测试状态
        
        $data['res'] = json_encode($data);
        /* 返回 */
        if (isset($_REQUEST['question'])) {
            /* get请求 */
            echo json_encode($data);
        } else {
            /* ajax请求 */
            $this->load->view('systemCheck/singleDebug', $data);
        }
    }

    /* 错误信息展示 */
    public function errorInfoShow()
    {
        $errorType = $this->getErrorType();
        $data['errorType'] = json_encode($errorType); // 设置错误类型
        $this->load->view('systemCheck/errorInfoShow', $data);
    }

    /* 错误信息查询 */
    public function getErrorInfo()
    {
        $data = array(
            'code' => 0,
            'msg' => ''
        );
        $errorType = isset($_REQUEST['errorType']) ? $_REQUEST['errorType'] : 0;
        $currentPage = isset($_REQUEST['currentPage']) ? $_REQUEST['currentPage'] : 1;
        $showNumber = isset($_REQUEST['showNumber']) ? $_REQUEST['showNumber'] : PAGE_SHOW_NUMBER;
        $condition = array();
        if (0 != $errorType) {
            $error = $this->getErrorType();
            $errorType = $error[$errorType];
            $condition = "error_type like '%$errorType%'";
        } else {
            $errorType = (int) $errorType;
        }
        $field = array(
            'id',
            'topic_id',
            'question',
            'error_type',
            'current_question',
            'error_word'
        );
        $order = 'id asc';
        $limit = array(
            'number' => $showNumber,
            'start' => ($currentPage - 1) * $showNumber
        );
        $result = $this->Debug->find($condition, $field, $order, $limit);
        if (empty($result)) {
            $data['msg'] = '暂无数据！';
        } else {
            /* 错误数获取 */
            $content = json_decode(file_get_contents(DEBUG_ALL_CACHE), true);
            $statisticalInfo = $content['response']['统计信息'];
            unset($content);
            if (0 === $errorType) {
                $currentErrorNumber = current(explode('|', $statisticalInfo['问句错误总数及占比']));
            } else {
                $tmp = isset($statisticalInfo['错误分类及占比'][$errorType]) ? $statisticalInfo['错误分类及占比'][$errorType] : array();
                $currentErrorNumber = current(explode('|', $tmp));
            }
            $statistica = array(
                'total' => $statisticalInfo['Debug问句总量'],
                'current' => $currentErrorNumber
            );
            
            /* 页码设置 */
            $count = $this->Debug->count($condition);
            $pageSet = array(
                'totalPage' => ceil($count / $showNumber),
                'showPage' => PAGE_NUMBER,
                'pageNumber' => (int) $currentPage,
                'totalCount' => $count,
                'showNumber' => (int) $showNumber
            );
            $data['code'] = 1;
            $data['msg'] = '查询成功！';
            $data['res'] = $result;
            $data['page'] = $pageSet;
            $data['statistica'] = $statistica;
        }
        echo json_encode($data);
    }

    /* debug全量模式(刷新) */
    public function debugAllModle()
    {
        /* 全量缓存，需要建定是脚本，一个小时内更新一次；在全量缓存前需要先更新问财那边的服务，调用接口 */
        $data = array(
            'code' => 0,
            'msg' => '刷新成功，5min后生效；耗时较长，请勿重复操作！'
        );
        file_put_contents(DEBUG_ALL_RUN_FLAG, '1');
        echo json_encode($data);
    }

    /* 全量debug查看 */
    public function showErrorInfo($id)
    {
        $data = array();
        $condition = array(
            'id' => $id
        );
        $result = $this->Debug->find($condition);
        if (empty($result)) {
            return false;
        }
        $info = $result[0];
        $key = $info['topic_id'] . '--' . $info['question'];
        $content = file_get_contents(DEBUG_ALL_CACHE);
        if ($content === false) {
            echo '缓存文件读取失败！';
            return false;
        } else {
            $content = json_decode($content, true);
        }
        $errorInfo = $content['response']['错误汇总'][$key];
        unset($content);
        $question = $info['question'];
        $topic['错误信息'] = current($errorInfo);
        $data = $this->singleDebugErrorType($topic);
        $data['question'] = $info['question'];
        $data['errorState'] = 'ERROR';
        $this->load->view('systemCheck/allDebug.php', $data);
    }

    /* 模拟对话 */
    public function simulationDialog()
    {
        $data = array();
        $condition = array(
            'parents' => 'ROOT'
        );
        $result = $this->TopicUnit->find($condition);
        $source = array();
        foreach ($result as $k => $v) {
            if (empty($v['source'])) {
                continue;
            }
            $source[$v['source']] = $v['topic_name'];
        }
        $data['source'] = json_encode($source); // 设置渠道
        $this->load->view('systemCheck/simulationDialog.php', $data);
    }

    /* 请求接口，获取问答 */
    public function simulationDialogOpt()
    {
        $data = array(
            'code' => 0,
            'msg' => ''
        );
        $question = isset($_REQUEST['question']) ? trim($_REQUEST['question']) : '';
        $source = isset($_REQUEST['source']) ? trim($_REQUEST['source']) : '';
        $newSession = isset($_REQUEST['newSession']) ? $_REQUEST['newSession'] : 1;
        if (empty($question)) {
            $data['msg'] = '问题不能为空!';
            echo json_encode($data);
            return false;
        }
        
        $cache = $this->session->cache;
        if (empty($cache['username']) || 0 == $newSession) {
            $user = $this->session->user;
            $username = $user['username'];
            $username = $username . time();
            $cache = $this->session->cache;
            $cache['username'] = $username;
            $this->session->cache = $cache;
        } else {
            $username = $cache['username'];
        }
        $sumulationDialog = sprintf(DEBUG_SIMULATION_DIALIG, urlencode($question), $username, $source, $newSession);
        $content = file_get_contents($sumulationDialog);
        $content = json_decode($content, true);
        if (false === $content) {
            $data['msg'] = '接口请求失败！';
            echo json_encode($data);
            return false;
        }
        $responseHead = $content['response_head'];
        if (0 != $responseHead['status']) {
            $data['msg'] = '服务错误！';
            echo json_encode($data);
            return false;
        }
        $response = $content['response'];
        /* 参数处理 */
        $macthInfo = isset($response['匹配信息']) ? $response['匹配信息'] : '';
        if ($macthInfo) {
            $pregPattern = "/({[^}]*})/";
            foreach ($macthInfo as $key => $value) {
                preg_match_all($pregPattern, $value['匹配句式'], $match);
                $macthInfo[$key]['匹配句式'] = implode(',', $match[0]);
                $tmp = explode('-', $value['匹配话题']);
                $macthInfo[$key]['匹配话题'] = next($tmp);
                $macthInfo[$key]['匹配分值'] = round($value['匹配分值'], 4);
            }
        }
        $segmentation = isset($response['词信息']['分词信息']) ? $response['词信息']['分词信息'] : ''; // 分词信息
        if ($segmentation) {
            foreach ($segmentation as $key => $value) {
                $tmp = rtrim($value, '/');
                $tmp = explode('/', $tmp);
                $tmp = array_unique($tmp);
                $tmp = implode('/', $tmp);
                $segmentation[$key] = $tmp;
            }
        }
        $distinguish = isset($response['词信息']['识别信息']) ? $response['词信息']['识别信息'] : ''; // 识别信息
        if ($distinguish) {
            foreach ($distinguish as $key => $value) {
                $tmp = rtrim($value, '/');
                $tmp = explode('/', $tmp);
                $tmp = array_unique($tmp);
                $tmp = implode('/', $tmp);
                $distinguish[$key] = $tmp;
            }
        }
        $res['answer'] = isset($response['问句答案']) ? $response['问句答案'] : $response['msg'];
        $res['segmentation'] = $segmentation;
        $res['distinguish'] = $distinguish;
        $res['slotInfo'] = isset($response['填槽信息']) ? $response['填槽信息'] : ''; // 填槽信息
        $res['macthInfo'] = $macthInfo; // 匹配信息
        $res['checkInfo'] = isset($response['话题检测信息']) ? $response['话题检测信息'] : ''; // 当前话题检测信息
        
        $data['code'] = 1;
        $data['msg'] = '获取数据成功！';
        $data['res'] = $res;
        echo json_encode($data);
    }

    /* 获取错误类型 */
    private function getErrorType()
    {
        $errorType = array(
            '全部',
            '所有词类未匹配',
            '业务方错误',
            '句式格式错误',
            '话题id不在解析库中',
            '未知错误',
            '匹配失败',
            '答案错误|话题错误',
            '答案正确|话题错误',
            '匹配不在|话题错误',
            '匹配存在|话题错误'
        );
        return $errorType;
    }

    /* 单例测试错误类型 */
    private function singleDebugErrorType($topic)
    {
        $data = array();
        $errorType = $topic['错误信息']['错误类型'];
        $data['errorType'] = $errorType;
        if ('未知错误' == $errorType) {
            $errorInfo = $topic['错误信息']['错误详情'];
            $data['errorInfo'] = $errorInfo['其他信息'];
        }
        $topicErrorInfo = $topic['错误信息']; // 错误信息
        /* 错误词类 */
        $expectationMatching = $topicErrorInfo['错误详情']['匹配信息']['期望匹配'];
        $expectationMatching = implode(',', $expectationMatching);
        $errorWord = '-';
        if ($expectationMatching) {
            $pattern = '/\$#([^#$]*)#\$/';
            preg_match_all($pattern, $expectationMatching, $matches);
            $errorWord = '';
            foreach ($matches[1] as $v) {
                $tmpErrorWord = explode('.', $v);
                $tmpErrorWord = end($tmpErrorWord);
                $errorWord .= ($tmpErrorWord . ',');
            }
            $errorWord = rtrim($errorWord, ',');
        }
        $newActualMatch = '-';
        $actualMatch = $topicErrorInfo['错误详情']['匹配信息']['实际匹配'];
        if ($actualMatch) {
            /* 实际匹配 */
            $actualMatch = $topicErrorInfo['错误详情']['匹配信息']['实际匹配'];
            $score = array();
            foreach ($actualMatch as $k => $v) {
                $score[] = $v['匹配分数'];
                $actualMatch[$k]['匹配分数'] = round($v['匹配分数'], 4);
                $actualMatch[$k]['匹配话题'] = ltrim(strstr($v['匹配话题'], '--'), '--');
            }
            arsort($score); // 降序
            $newActualMatch = '';
            $count = 1;
            foreach ($score as $k => $v) {
                $newActualMatch .= $count ++ . ".分数：{$actualMatch[$k]['匹配分数']} 问题：{$actualMatch[$k]['匹配话题']}<br>";
            }
        }
        /* 分词信息 */
        $segmentation = $topicErrorInfo['错误详情']['词信息']['分词信息']; // 分词信息
        $newSegmentation = '';
        foreach ($segmentation as $k => $v) {
            $tmp = explode('/', trim($v));
            $tmp = array_unique($tmp);
            $tmp = implode('/', $tmp);
            $tmp = rtrim($tmp, '/');
            $newSegmentation .= "<div style=\"clear:both;\"><span style=\"width:15%;float:left;\">$k:</span><spna style=\"width:85%;float:left;\">$tmp</span></div>";
        }
        /* 识别信息 */
        $distinguish = $topicErrorInfo['错误详情']['词信息']['识别信息']; // 识别信息
        $newDistinguish = '';
        foreach ($distinguish as $k => $v) {
            $tmp = explode('/', trim($v));
            $tmp = array_unique($tmp);
            $tmp = implode('/', $tmp);
            $tmp = rtrim($tmp, '/');
            $newDistinguish .= "<div style=\"clear:both;\"><span style=\"width:15%;float:left;\">$k:</span><spna style=\"width:85%;float:left;\">$tmp</span></div>";
        }
        /* 返回值 */
        $data['selectQuestion'] = isset($topicErrorInfo['当前选中话题']) ? ltrim(strstr($topicErrorInfo['当前选中话题'], '--'), '--') : '-'; // 当前选中问题
        $data['segmentation'] = $newSegmentation; // 分词信息
        $data['distinguish'] = $newDistinguish; // 识别信息
        $data['errorWord'] = $errorWord; // 错误词类
        $data['actualMatch'] = $newActualMatch; // 实际匹配
        return $data;
    }
}